package scrshotcombine

import (
	"bytes"
	"gmap-backend/internal/config"
	"gmap-backend/internal/server/vo"
	"gmap-backend/internal/util/imgutil"
	"image"
	"image/color"
	"image/draw"
	_ "image/gif"
	_ "image/jpeg"
	_ "image/png"
	"os"
	"path/filepath"
	"strings"
	"unsafe"
)

func CombineImg(appConfig *config.AppConfig, req *vo.CombineShotReq, bins [][]byte) {
	// 把片段合并
	factW, factH := req.SumSize.Width, req.SumSize.Height
	bgImg := image.NewRGBA(image.Rect(0, 0, req.SumSize.Width, req.SumSize.Height))
	draw.Draw(bgImg, bgImg.Bounds(), &image.Uniform{C: color.Gray16{Y: 0xFFFF}}, image.Point{}, draw.Src)
	for i, item := range req.Items {
		im, _, e := image.Decode(bytes.NewBuffer(bins[i]))
		if nil != e {
			panic("图片格式有误")
		}
		draw.Draw(bgImg, image.Rect(item.X1, item.Y1, item.X2, item.Y2), im, image.Pt(0, 0), draw.Over)
	}

	// 指定了有效区域，则裁剪，水平方向取中间部分，垂直方向从上向下取
	if req.ForceValidSize {
		fromX := 0

		if req.ValidSize.Width > 0 && req.ValidSize.Width < req.SumSize.Width {
			factW = req.ValidSize.Width
			fromX = (req.SumSize.Width - req.ValidSize.Width) / 2
		}
		if req.ValidSize.Height > 0 && req.ValidSize.Height < req.SumSize.Height {
			factH = req.ValidSize.Height
		}

		tmpImg := image.NewRGBA(image.Rect(0, 0, factW, factH))
		draw.Draw(tmpImg, tmpImg.Bounds(), &image.Uniform{C: color.Gray16{Y: 0xFFFF}}, image.Point{}, draw.Src)
		draw.Draw(tmpImg, image.Rect(0, 0, factW, factH), bgImg, image.Pt(fromX, 0), draw.Over)
		bgImg = tmpImg
	}

	// 按不同格式导出：存入剪切板、存为图片、存为pdf、存为word等
	// 保存截图到剪切板
	if vo.CombineShotResultMem == req.ResultType {
		bs, err := imgutil.EncodeImgToBytes(bgImg, imgutil.FIXED_EXT_JPG)
		if nil != err {
			panic("图片操作时出现错误")
		}
		rs, _, _ := appConfig.Win32LibConfig.SaveImgBytesToClipboard.Call(uintptr(unsafe.Pointer(&bs[0])), uintptr(len(bs)))
		if 0 != rs {
			panic("图片操作时出现错误")
		}
		return
	}
	// 导出为图片文件，只支持jpg/png/gif编码器，对其它扩展名也使用jpg编码器
	if vo.CombineShotResultImg == req.ResultType {
		f, err := os.OpenFile(req.ResultPath, os.O_CREATE|os.O_RDWR, 0666)
		if nil != err {
			panic("图片操作时出现错误")
		}
		defer f.Close()

		ext := strings.TrimSpace(strings.ToLower(filepath.Ext(req.ResultPath)))
		err = imgutil.EncodeImg(bgImg, f, ext)
		if nil != err {
			panic("图片操作时出现错误")
		}
		return
	}
	// 导出pdf
	// 导出节点部分时为单页，导出引用部分为时多页，处理逻辑不一样
	if vo.CombineShotResultPdf == req.ResultType {
		savePdf(bgImg, req.ResultMultiPage, req.ResultPath)
		return
	}
	// 导出docx
	if vo.CombineShotResultDoc == req.ResultType {
		saveDocx(bgImg, factW, factH, req.ResultMultiPage, req.ResultPath)
		return
	}
	panic("未知的导出类型")
}
